package com.xgr.wonderful.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.R.integer;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Bitmap.Config;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;

/**
 * 分两个部分，前面是图片的处理，后面是照片的选取
 * @author lsj
 *
 */
public class BitmapUtils {
	/**
	 * *********bitmap处理相关 ************************
	 */
	
	private static String TAG = "BitmapUtils";
	/**
	 * return bitmap without compress
	 * @param activity
	 * @param uri
	 */
	public static Bitmap decodeUriAsBitmap(Context context,Uri uri){
		Bitmap bitmap=null;
		Log.i(TAG, "decodeUriAsBitmap uri:"+uri.toString());
		try {
			bitmap= BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		if (bitmap!=null){
			LogUtils.i(TAG, "bitmap!=null");
			return bitmap;
		}else {
			LogUtils.i(TAG, "bitmap==null");
			return null;
		}
	}
	/**
	 * 将图片保存到本地时进行压缩 ，也就是将图片从bitmap形式变为File形式时进行压缩 。
	 * 特点是：File形式的图片确定被压缩了，但是当你重新读取压缩后的File为bitmap时，它占用的内存并没有变化。
	 * 这个方法是压缩图片的质量，但是不会减少图片的像素。经过这种方法的压缩后，File形式的图片是100以下 ，以方便上传 到服务器
	 * @param bmp
	 * @param file
	 */
	public static void compressBitmpToFile (Bitmap bmp ,File file){
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int options = 80;//个人喜欢从80开始,80时压缩效果比较好，70时已经不那么 明显了
        bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
        while (baos.toByteArray().length / 1024 > 100) {
            baos.reset();
            options -= 10;
            bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
        }
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(baos.toByteArray());
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }	
	/**
	 * 将图片保存到本地时进行压缩 ，也就是将图片从bitmap形式变为File形式时进行压缩 。
	 * 特点是：File形式的图片确定被压缩了，但是当你重新读取压缩后的File为bitmap时，它占用的内存并没有变化。
	 * 这个方法是压缩图片的质量，但是不会减少图片的像素。经过这种方法的压缩后，File形式的图片是100以下 ，以方便上传 到服务器
	 * @param context
	 * @param bitmap
	 * @param filename
	 * @param target (k)
	 * @return  cache路径/image/filename
	 */
	public static String compressBmpAndSaveToFile(Context context, Bitmap bmp, String filename,int target ){
		File file = new File(CacheUtils.getCacheDirectory(context, 
				true, "image")+File.separator+ filename) ;
		if (!file.exists()|| file.length()==0){
			return null ;
		}
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int options = 80;
        bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
        while (baos.toByteArray().length / 1024 > target) {
            baos.reset();
            options -= 10;
            bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
            LogUtils.i(TAG, "options:"+options+",length:"+baos.toByteArray().length/1024) ;
        }
        try {
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(baos.toByteArray());
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
		return file.getAbsolutePath() ;
	}
	/**
	 * 不压缩的保存到本地的方法
	 * @param context
	 * @param bitmap
	 * @param fileName
	 * @return
	 */
	public static String saveToFile(Context context, Bitmap bitmap, String fileName){
		File file = new File(CacheUtils.getCacheDirectory(context, true, "image") + 
				File.separator + fileName);
		if (!file.exists() || file.length()== 0){
			return null ;
		}
        try {
            FileOutputStream out=new FileOutputStream(file);
            if(bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)){
                out.flush();
                out.close();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return file.getAbsolutePath();
	}
	/**
	 * 图片按比例大小压缩方法
	 * 从file读取到内存时的压缩
	 * @param filepath
	 * @return
	 */
	public static Bitmap compressBitmapFromFile(String filepath){
		BitmapFactory.Options newOpts = new BitmapFactory.Options() ;
		//If set to true, the decoder will return null (no bitmap), 
		//but the out... fields will still be set, 
		//allowing the caller to query the bitmap without 
		//having to allocate the memory for its pixels. 
		newOpts.inJustDecodeBounds = true ;
		//Options that control downsampling and whether the image
		//should be completely decoded, or just is size returned.
		Bitmap bitmap = BitmapFactory.decodeFile(filepath, newOpts) ;
		
		newOpts.inJustDecodeBounds = false ;
		int w = newOpts.outWidth ;//The resulting width of the bitmap.
		int h = newOpts.outHeight ; 
		
		float hh = 800f  ;
		float ww = 480f ;
		int be =1 ;
		if (w > h && w> ww){
			be = (int )(newOpts.outWidth/ ww); 
		}else if (w< h && h>hh) {
			be = (int)(newOpts.outHeight/ hh);
		}
		if (be<=0){
			be=1;
		}
		newOpts.inSampleSize = be ;//采样率
		newOpts.inPreferredConfig = Config.ARGB_8888 ;
		newOpts.inPurgeable = true ;
		newOpts.inInputShareable = true;
		
		bitmap = BitmapFactory.decodeFile(filepath, newOpts) ;
		return bitmap ;
	}
	/**
	 * 质量压缩方法，内存中压缩
	 * 在MyInfo中用的这个 ，因为图片先进行了crop，大小过大，不会再产生outofmemory
	 * @param image
	 * @param target
	 * @return bitmap less than target(k)
	 */
	public static  Bitmap compressImage(Bitmap image, long target) {  
		   
        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
        //质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中  
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int options = 100;  
      //循环判断如果压缩后图片是否大于100kb,大于继续压缩    
        LogUtils.i(TAG, "before:"+ getBitmapSize(image));
        while ( baos.toByteArray().length / 1024>target) { 
            baos.reset();//重置baos即清空baos  
            //这里压缩options%，把压缩后的数据存放到baos中  ,实际 30%都 不错
            options -= 10;
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
            LogUtils.i(TAG, "options:"+ options) ;
        	LogUtils.i(TAG, "length:"+ baos.toByteArray().length/1024) ;
        }  
       
        //把压缩后的数据baos存放到ByteArrayInputStream中  
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
        LogUtils.i(TAG, "after:"+ getBitmapSize(bitmap));
        return bitmap;  
    }
	
	/**
	 * 流的形式: 讲图片文件读到内存输入流中,看它的byte数
	 * 看的是内存中的bitmap大小 ？没有用
	 * @param bitmap
	 * @return  k
	 */
	public static int getBitmapSize(Bitmap bitmap){
		 ByteArrayOutputStream baos = new ByteArrayOutputStream();  
	     bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
	     return baos.toByteArray().length /1024;
	}
	
	/**
	 * 在固定大小的ImageView中，保证图片不变形
	 * @param bitmap
	 * @param imageView
	 * @param width  一般情况下是全屏的
	 * @param height
	 */
	public static void setBestBitmap(Bitmap  bitmap , ImageView imageView, int width,
			int height ){
		LogUtils.i(TAG, "screen width:"+width );
		LogUtils.i(TAG, "screen height:"+height);
		
		//计算最好缩放倍数
		float scaleX = (float)width/bitmap.getWidth() ;
		float scaleY = (float)height/bitmap.getHeight() ;
		
		LogUtils.i(TAG, "bitmap width:"+bitmap.getWidth() );
		LogUtils.i(TAG, "bitmap height:"+bitmap.getHeight());
		//取小者
		float bestScale = scaleX < scaleY? scaleX : scaleY ;
		
		LogUtils.i(TAG, "bestScale:"+ bestScale) ;
		//为了移到中心位置 
		float subX = (width - bitmap.getWidth()*bestScale)/2;
		float subY = (height - bitmap.getHeight()*bestScale)/2;
		LogUtils.i(TAG, "subX:"+subX+";subY:"+subY );
			
		Matrix  imageMatrix = new Matrix() ;
		imageView.setScaleType(ScaleType.MATRIX ) ;
		// 缩放最佳大小
		imageMatrix.postScale(bestScale, bestScale) ;
		//移动 居中
		imageMatrix.postTranslate(subX, subY) ;
		//设置matrix 
		imageView.setImageMatrix(imageMatrix);
		
		imageView.setImageBitmap(bitmap) ;
		
	}
	
	
	/**
	 * *********下面的与照片的选取 有关 ****************
	 */
	private static  String[] choice = new String []{"相册","拍照"};
	
	public static final int CAMERA_REQUEST=1;
	public static final int CROPED_REQUEST=2;
	public static final int ALBUM_REQUESRT=3;
	
	public static void showGetImgeDialog(final Activity activity, final File f){
		new AlertDialog.Builder(activity )
		.setItems(choice, new OnClickListener() {
			
			@Override
			public void onClick(DialogInterface dialog, int which) {
				switch (which) {
				case 0://album 
					getImageFromAlbum(activity) ;
					break;
				case 1: ///camera
					getImageFromCamera(activity, f) ;
					break ;

				default:
					break;
				}
			}
		}).setNegativeButton("取消", null).show() ;
	}
	
	private static void getImageFromAlbum(Activity activity){
		Intent albumIntent = new Intent(Intent.ACTION_PICK,
				MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
		activity.startActivityForResult(albumIntent, ALBUM_REQUESRT);
	}
	
	private static void getImageFromCamera(Activity activity , File f ){
		Uri uri = Uri.fromFile(f) ;
		Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
		activity.startActivityForResult(cameraIntent, CAMERA_REQUEST);
	}
	
	/**
	 * 
	 * @param activity
	 * @param fromUri
	 * @param saveUri 
	 * @param outputX  是裁剪图片宽高
	 * @param outputY
	 * @param aspX  是裁剪框的比例
	 * @param aspY
	 */
	public static void startImageZoom(Activity activity, Uri fromUri,
			Uri saveUri, int outputX, int outputY, int aspX, int aspY){
	
		Intent cropIntent = new Intent("com.android.camera.action.CROP");
		cropIntent.setDataAndType(fromUri, "image/*");
		cropIntent.putExtra("crop" ,true);
		//设置aspectX 与 aspectY 后，裁剪框会按照所指定的比例出现，
		//放大缩小都不会更改。如果不指定，那么 裁剪框就可以随意调整了。
		cropIntent.putExtra("aspectX", aspX);
		cropIntent.putExtra("aspectY", aspY);
		//返回数据的时候的 X 像素大小
		cropIntent.putExtra("outputX", outputX);
		cropIntent.putExtra("outputY", outputY);
		//以上两个值，设置之后会按照两个值生成一个Bitmap, 
	    //两个值就是这个bitmap的横向和纵向的像素值，如果裁剪的图
		//像和这个像素值不符合，那么空白部分以黑色填充。
		cropIntent.putExtra("scale", true);

		cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);
		cropIntent.putExtra("return-data", false);
		cropIntent.putExtra("outputFormat",
				Bitmap.CompressFormat.JPEG.toString());
		// 是否去除面部检测， 如果你需要特定的比例去裁剪图片，那么这个一定要去掉，因为它会破坏掉特定的比例
		cropIntent.putExtra("noFaceDetection",  true);
		activity.startActivityForResult(cropIntent, CROPED_REQUEST);
	}
	
	public static String uriToPath (Uri uri, Context context){
		String[] proj = { MediaStore.Images.Media.DATA };
		//查询，返回cursor
		Cursor cursor = context.getContentResolver().query(uri, proj,   
		null, null, null); 
		int colum_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
		cursor.moveToFirst();
		return cursor.getString(colum_index)  ;
	}
	
}
